<script setup>
import axios from 'axios'
import { inject, watch, ref, computed, onBeforeUnmount } from 'vue'
const { map, scene } = inject('mapScene') // 注入 map 和 scene 响应式变量

// 引入导航控件
import NavigationControl from '@mapbox/mapbox-gl-directions/dist/mapbox-gl-directions.js'
// 引入导航控件样式
import '@mapbox/mapbox-gl-directions/dist/mapbox-gl-directions.css'
// 引入绘制控件
import MapboxDraw from '@mapbox/mapbox-gl-draw'
// 引入绘图控件样式
import '@mapbox/mapbox-gl-draw/dist/mapbox-gl-draw.css'
// 引入turf.js
import * as turf from '@turf/turf'
// 引入点图层
import { PointLayer } from '@antv/l7'

// 图层管理函数
import { useCityLayers } from '@/composable/useCityLayers.js'
// 使用图层管理函数 显示/隐藏/更新功能
const { layerList, showLayerByName, hideLayerByName, updateLayerList } = useCityLayers()

// 当我点击导航按钮时，显示/隐藏导航控件
const showNavigation = ref(false) // 是否显示导航控件
let navControl = null // 存储导航控件实例
function toggleNavigation() {
  showNavigation.value = !showNavigation.value
  if (map.value === null) return
  if (showNavigation.value) {
    navControl = new NavigationControl()
    map.value.addControl(navControl, 'top-left')
  } else {
    map.value.removeControl(navControl)
  }
}

// 图层按钮 点击切换下拉菜单显示/隐藏
const showLayerDropdown = ref(false)
function onLayerBtn() {
  showLayerDropdown.value = !showLayerDropdown.value
}

/**
用layerList初始化layerEntries
使用computed从layerList派生layerEntries
[{ name: 'building', present: true }, { name: 'roads', present: false }]
*/
const layerEntries = computed(() =>
  layerList.value.map((layer) => ({
    name: layer.name,
    present: layer.visible,
  })),
)

// 切换图层时调用
async function toggleLayerEntry(layerName) {
  const layer = layerList.value.find((layer) => layer.name === layerName)
  if (!layer) return
  // 如果图层处于显示状态，就隐藏它，反之则显示
  if (layer.visible) {
    hideLayerByName(scene.value, layerName)
  } else {
    showLayerByName(scene.value, layerName)
  }
  // 更新layerList
  updateLayerList(scene.value)
}

// 使用mapbox-gl-draw绘制控件
const showDraw = ref(false) // 是否显示绘制控件
let drawControl = null // 存储绘制控件实例
function toggleDraw() {
  showDraw.value = !showDraw.value
  if (map.value === null) return
  if (showDraw.value) {
    drawControl = new MapboxDraw({
      displayControlsDefault: false,
      controls: {
        polygon: true,
        trash: true,
      },
    })
    map.value.addControl(drawControl)

    // 监听绘制完成事件  http://localhost:3001/Wuhan_events
    map.value.on('draw.create', intersectDrawnFeatures)
    // 监听销毁事件
    map.value.on('draw.delete', removeSelectedPointLayer)
    // 监听更新事件
    map.value.on('draw.update', removeSelectedPointLayer)
  } else {
    // 注销事件并移除控件
    map.value.off('draw.create', intersectDrawnFeatures)
    map.value.removeControl(drawControl)
  }
}

// 多边形内点属性获取用于表格显示
const selectedPoints = ref([])

// 绘制完成的回调函数 获取绘制的图形 和页面点图层求交
async function intersectDrawnFeatures(e) {
  const data = drawControl.getAll()
  // console.log('绘制完成，获取绘制的图形数据：', data)
  // 从链接中获取点图层数据，并与绘制的图形求交
  const res = await axios.get('http://localhost:3001/Wuhan_events')
  // console.log(res.data)
  // 获取在多边形内的点
  const pointsWithin = turf.pointsWithinPolygon(res.data, data.features[0])
  // 将这些点显示在表格中
  console.log('在多边形内的点：', pointsWithin)
  selectedPoints.value = pointsWithin.features.map((feature) => {
    return {
      coordinates: feature.geometry.coordinates,
      ...feature.properties,
    }
  })

  // 将这些点用scene.addLayer添加到地图上
  addPointLayer(scene.value, pointsWithin)
}

// scene.addLayer函数逻辑
function addPointLayer(scene, data) {
  if (!scene) return
  const pointLayer = new PointLayer({
    zIndex: 1,
    name: 'selectedEventPoint',
  })
  pointLayer
    .source(data)
    .size(10)
    .shape('circle')
    .active(true)
    .animate(true)
    .size(40)
    .color('rgb(244, 67, 54)')
    .style({
      offsets: [40, 40],
    })
  scene.addLayer(pointLayer)
  // 添加完图层后，更新图层管理模块的图层状态数据
  updateLayerList(scene)
}

// 绘制销毁的回调函数 删除查找到的点图层 清空表格数据
function removeSelectedPointLayer() {
  if (!scene.value) return
  const layer = scene.value.getLayerByName('selectedEventPoint')
  scene.value.removeLayer(layer)
  updateLayerList(scene.value)
  selectedPoints.value = []
}

// 点击表格项，flyTo对应点
function flyToPoint(coord) {
  map.value.flyTo({
    center: coord,
    zoom: 11,
    pitch: 0,
    bearing: 0,
  })
}

// 组件卸载时移除控件和图层
onBeforeUnmount(() => {
  if (showNavigation.value && map.value && navControl) {
    map.value.removeControl(navControl)
  }
  if (showDraw.value && map.value && drawControl) {
    map.value.off('draw.create', intersectDrawnFeatures)
    map.value.removeControl(drawControl)
  }
  // 移除点图层
  const layer = scene.value.getLayerByName('selectedEventPoint')
  if (layer) {
    scene.value.removeLayer(layer)
    updateLayerList(scene.value)
  }
})
</script>

<template>
  <div class="top-area">
    <header class="header">
      <div class="logo">
        <span class="white-big">Gis</span>
        <span class="grey-middle">system</span>
      </div>
      <div class="nav-buttons">
        <button class="btn menu" title="菜单">
          <i class="iconfont icon-caidan"></i>
        </button>
        <button class="btn layer" title="图层" @click="onLayerBtn">
          <i class="iconfont icon-ditu-youxia-tuceng"></i>
        </button>
        <button class="btn navigation" title="导航" @click="toggleNavigation">
          <i class="iconfont icon-daohang"></i>
        </button>
        <button class="btn locate" title="定位">
          <i class="iconfont icon-dingwei"></i>
        </button>
        <button class="btn weather" title="天气">
          <i class="iconfont icon-leiyu"></i>
        </button>
        <button class="btn search" title="拉框查找" @click="toggleDraw">
          <i class="iconfont icon-pull-box-search"></i>
        </button>
      </div>
    </header>
  </div>

  <!-- 图层下拉菜单 -->
  <div v-if="showLayerDropdown" class="layer-dropdown">
    <ul v-if="layerEntries.length">
      <li v-for="entry in layerEntries" :key="entry.name">
        <input
          type="checkbox"
          :checked="entry.present"
          @change="() => toggleLayerEntry(entry.name)"
        />
        <span>{{ entry.name }}</span>
      </li>
    </ul>
    <ul v-else>
      <li style="font-size: 12px; color: gray">暂无图层</li>
    </ul>
  </div>

  <!-- 点图层列表 -->
  <div v-if="selectedPoints.length" class="selected-points">
    <table>
      <thead>
        <tr>
          <th>事件编号</th>
          <th>事件类型</th>
          <th>等级</th>
          <th>事故地点</th>
          <th>涉事车辆</th>
          <th>驾驶员号码</th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="point in selectedPoints" :key="point.id" @click="flyToPoint(point.coordinates)">
          <td>{{ point.event_num }}</td>
          <td>{{ point.name }}</td>
          <td>{{ point.level }}</td>
          <td>{{ point.area }}</td>
          <td>{{ point.car_num }}</td>
          <td>{{ point.phone }}</td>
        </tr>
      </tbody>
    </table>
  </div>
</template>

<style scoped>
.top-area {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 10;
  color: white;
}
.header {
  display: flex;
  gap: 60px;
  width: fit-content;
  padding: 10px 20px;
  /* border: 1px solid white; */
}
.header .logo {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;

  width: 165px;
  height: 57px;
  background-color: rgba(0, 0, 0, 0.8);
  border-radius: 25px;
  .white-big {
    font-size: 24px;
    font-weight: bold;
    color: white;
  }
  .grey-middle {
    font-weight: 600;
    color: grey;
  }
}
.header .nav-buttons {
  display: flex;
  gap: 10px;
  height: 57px;
  cursor: pointer;
  .btn {
    display: flex;
    justify-content: center;
    align-items: center;
    width: 57px;
    height: 57px;
    border-radius: 47%;
    background-color: rgba(0, 0, 0, 0.8);
    .iconfont {
      font-size: 22.5px;
      color: rgb(33, 150, 243);
    }
  }
}
.header .nav-buttons .btn:hover {
  background-image: linear-gradient(to bottom, rgb(144, 202, 249), rgb(25, 118, 210));
  .iconfont {
    color: white;
  }
}

/* 图层下拉菜单 */
.layer-dropdown {
  position: absolute;
  top: 74px;
  left: 313px;
  z-index: 20;
  width: auto;
  background: rgba(0, 0, 0, 0.8);
  border-radius: 8px;
  color: white;
  cursor: pointer;
}
/* 下拉菜单添加三角伪元素 */
.layer-dropdown:after {
  content: '';
  position: absolute;
  top: -8px;
  left: 16px;
  border-width: 4px;
  border-style: solid;
  border-color: transparent transparent rgba(255, 255, 255, 1) transparent;
}
.layer-dropdown ul {
  padding: 4px 0;
}
.layer-dropdown li:hover {
  background-color: white;
}
.layer-dropdown li {
  display: flex;
  align-items: center;
  height: 24px;
  padding: 0 16px;
}
.layer-dropdown li span {
  padding: 0 5px;
  margin-left: 5px;
  font-weight: 400;
  font-size: 12px;
  line-height: 24px;
  color: gray;
}

/* 点图层列表 */
.selected-points {
  position: absolute;
  top: 587px;
  left: 50%;
  transform: translateX(-50%);
  max-height: 200px;
  overflow-y: auto;
  background: rgba(0, 0, 0, 0.8);
  border-radius: 8px;
  padding: 12px 16px;
  color: white;
  z-index: 10;
}
.selected-points table {
  border-collapse: collapse;
  width: 100%;
  /* 最高高度为200px 超出添加滚动条 */

  cursor: pointer;
}
.selected-points th,
.selected-points td {
  border-top: 1px solid #ddd;
  border-bottom: 1px solid #ddd;
  padding: 4px 8px;
  font-size: 12px;
  white-space: nowrap;
  text-align: center;
}
.selected-points tbody tr:nth-child(even) {
  background-color: rgba(255, 255, 255, 0.1);
}
.selected-points tbody tr:hover {
  background-color: rgba(255, 255, 255, 0.3);
}
/* 滚动条样式 */
/* 设置滚动条整体部分样式 */
.selected-points {
  scrollbar-width: thin; /* "auto" or "thin" */
  scrollbar-color: rgba(255, 255, 255, 0.5) transparent; /* thumb and track */
}
</style>
